home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / b / b.lha / B / src / bed / line.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-11-24  |  4.2 KB  |  239 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
  2. static char rcsid[] = "$Header: line.c,v 2.4 85/08/22 16:04:53 timo Exp $";
  3.  
  4. /*
  5.  * B editor -- Routines for treating the parse tree as a sequence of lines.
  6.  *
  7.  * WARNING: The routines in this file (and many others!) assume that a
  8.  * `newline' can only occur in the zero'th representation string of a node
  9.  * (i.e., rp[0]).
  10.  */
  11.  
  12. #include "b.h"
  13. #include "bobj.h"
  14. #include "node.h"
  15. #include "gram.h"
  16. #include "supr.h"
  17.  
  18.  
  19. /*
  20.  * Compute equality of subtrees, based on common descent.
  21.  * Strings are not checked for characterwise equality, but must
  22.  * be the same pointer; other nodes must have the same symbol and
  23.  * their children must be equal in this sense (equal pointers are
  24.  * always used as a shortcut).
  25.  *
  26.  * (Used by screen update algorithm only.)
  27.  */
  28.  
  29. Visible bool
  30. eqlines(n1, n2)
  31.     node n1;
  32.     node n2;
  33. {
  34.     register node nn1;
  35.     register node nn2;
  36.     register int w1;
  37.     register int w2;
  38.     register int nch;
  39.     register int i;
  40.  
  41.     if (n1 == n2)
  42.         return Yes;
  43.     if (Type(n1) != Nod || Type(n2) != Nod)
  44.         return No;
  45.     if (symbol(n1) != symbol(n2))
  46.         return No;
  47.     nch = nchildren(n1);
  48.     Assert(nch == nchildren(n2));
  49.     for (i = 1; i <= nch; ++i) {
  50.         nn1 = child(n1, i);
  51.         nn2 = child(n2, i);
  52.         w1 = width(nn1);
  53.         w2 = width(nn2);
  54.         if (w1 >= 0 && w2 >= 0) {
  55.             if (!eqlines(nn1, nn2))
  56.                 return No;
  57.         }
  58.         else {
  59.             if (nn1 == nn2)
  60.                 return Yes;
  61.             if (fwidth(noderepr(nn1)[0]) < 0 || fwidth(noderepr(nn2)[0]) < 0)
  62.                 return linelen(n1) == linelen(n2);
  63.             return eqlines(nn1, nn2);
  64.         }
  65.     }
  66.     return Yes;
  67. }
  68.  
  69.  
  70. /*
  71.  * Compute the length of the line beginning at the current node.
  72.  */
  73.  
  74. Visible int
  75. linelen(n)
  76.     node n;
  77. {
  78.     register node nn;
  79.     register string *rp = noderepr(n);
  80.     register int w;
  81.     register int nch = nchildren(n);
  82.     register int i;
  83.     register int len = fwidth(rp[0]);
  84.  
  85.     if (len < 0)
  86.         len = 0;
  87.     for (i = 1; i <= nch; ++i) {
  88.         nn = child(n, i);
  89.         w = width(nn);
  90.         if (w >= 0)
  91.             len += w;
  92.         else {
  93.             n = nn;
  94.             i = 0;
  95.             nch = nchildren(n);
  96.             rp = noderepr(n);
  97.         }
  98.         w = Fwidth(rp[i]);
  99.         if (w < 0)
  100.             break;
  101.         len += w;
  102.     }
  103.     return len;
  104. }
  105.  
  106.  
  107. /*
  108.  * Move the focus to the next line.
  109.  * NB: This is a building block for use in the 'show' module;
  110.  * it cannot set ep->mode or call higher() properly!
  111.  */
  112.  
  113. Visible bool
  114. nextline(pp)
  115.     register path *pp;
  116. {
  117.     register node n;
  118.     register node nn;
  119.     register int w;
  120.     register int nch;
  121.     register int i = 0;
  122.  
  123.     for (;;) {
  124.         n = tree(*pp);
  125.         if (width(n) < 0) {
  126.             nch = nchildren(n);
  127.             while (++i <= nch) {
  128.                 nn = child(n, i);
  129.                 w = width(nn);
  130.                 if (w < 0) {
  131.                     downi(pp, i) || Abort();
  132.                     n = tree(*pp);
  133.                     if (fwidth(noderepr(n)[0]) < 0)
  134.                         return Yes;
  135.                     nch = nchildren(n);
  136.                     i = 0;
  137.                 }
  138.             }
  139.         }
  140.         /* Must go upward in the tree */
  141.         i = ichild(*pp);
  142.         if (!up(pp))
  143.             return No;
  144.     }
  145. }
  146.  
  147.  
  148. /*
  149.  * Compute the current line number.  If the current node begins with
  150.  * a `newline', add one because the first character is actually
  151.  * on the next line.
  152.  */
  153.  
  154. Visible int
  155. lineno(ep)
  156.     register environ *ep;
  157. {
  158.     register int y;
  159.  
  160.     y = -focoffset(ep);
  161.     if (y < 0)
  162.         y = 0;
  163.     if (focchar(ep) == '\n')
  164.         ++y;
  165.     return y + Ycoord(ep->focus);
  166. }
  167.  
  168. /*
  169.  * Similarly, compute the current column number.
  170.  * (Hope the abovementioned trick isn't necessary.)
  171.  */
  172.  
  173. Visible int
  174. colno(ep)
  175.     environ *ep;
  176. {
  177.     int x= focoffset(ep);
  178.  
  179.     if (x < 0)
  180.         x= 0; /* In fact, give up */
  181.     return x + Xcoord(ep->focus);
  182. }
  183.  
  184.  
  185. /*
  186.  * Make the focus exactly one line wide (if at all possible).
  187.  */
  188.  
  189. Visible Procedure
  190. oneline(ep)
  191.     register environ *ep;
  192. {
  193.     register node n;
  194.     node nn;
  195.     register string *rp;
  196.     register int s1;
  197.     register int s2;
  198.     register int len;
  199.     int ich;
  200.     int nch;
  201.  
  202.     ich = 1;
  203.     while (width(tree(ep->focus)) >= 0) {
  204.         ich = ichild(ep->focus);
  205.         if (!up(&ep->focus)) {
  206.             ep->mode = WHOLE;
  207.             higher(ep);
  208.             return;
  209.         }
  210.     }
  211.     higher(ep);
  212.     n = tree(ep->focus);
  213.     nch = nchildren(n);
  214.     rp = noderepr(n);
  215.     for (s1 = 2*ich-1; s1 >= 1; --s1) {
  216.         if (s1&1)
  217.             len = fwidth(rp[s1/2]);
  218.         else {
  219.             nn = child(n, s1/2);
  220.             len = width(nn);
  221.         }
  222.         if (len < 0)
  223.             break;
  224.     }
  225.     for (s2 = 2*ich+1; s2 <= 2*nch+1; ++s2) {
  226.         if (s2&1)
  227.             len = fwidth(rp[s2/2]);
  228.         else {
  229.             nn = child(n, s2/2);
  230.             len = width(nn);
  231.         }
  232.         if (len < 0)
  233.             break;
  234.     }
  235.     ep->mode = SUBSET;
  236.     ep->s1 = s1+1;
  237.     ep->s2 = s2-1;
  238. }
  239.